package triIndex.btree;

import transaction.Transaction;
import triStorage.*;

public class BTree {

	private static final int DEFAULT_ROOT_PAGEID = 0;
	
	public static final int ERROR_CODE = -1;
	
	private int order;
	
	private BRoot root;
	
	private NodeFactory factory;
	
	private TriMMPFile mmpfile;
	
	public BTree(String filename, int bufferSize, int pageSize, int order) {
		this.order = order;
		//this.diskfile = new TriDiskFile(filename);
		//this.mmpfile = new TriMMPFile(diskfile, bufferSize, pageSize);
		this.mmpfile = new TriMMPFile(filename, bufferSize + 1, pageSize);
		this.factory = new NodeFactory(bufferSize, pageSize, mmpfile);		
	}
	
	public void init(Transaction tx) {
		if (mmpfile.open()) {
			mmpfile.allocNewPage();
			setRootPageId(DEFAULT_ROOT_PAGEID, tx);
			//factory.init(DEFAULT_ROOT_PAGEID - 1);
			root = new BRoot(this.order, factory);
			root.setNode(factory.createNewLeaf(this.order, -1, tx));
		}
		else {			
			int rootId = getRootNodeId(tx);
			//factory.init();
			root = new BRoot(this.order, factory);
			root.setNode(factory.getNode(rootId, this.order, tx));
		}
	}
	
	public int find(int key, Transaction tx) {
		return root.find(key, tx);
	}
	
	synchronized public void insert(int key, int value, Transaction tx) {
		root.insert(key, value, tx);
		this.setRootPageId(root.getRootNodeId(), tx);
	}
	
	public void dispose(Transaction tx) {
		save(tx);
		factory.dispose();
	}
	
	private void save(Transaction tx) {
		factory.flushToDisk(tx);
	}
	
	//byte[] intbuffer = new byte[Constants.INT_SIZE];
	
	private void setRootPageId(int pageId, Transaction tx) {
		/*Converter.Int2Bytes(pageId, intbuffer, 0);
		diskfile.write(0, intbuffer, 0, Constants.INT_SIZE);*/
		//System.out.println("Set BTree root = " + pageId);
		mmpfile.writeInt(0, 0, pageId, tx);
	}
	
	private int getRootNodeId(Transaction tx) {
		/*diskfile.read(0, intbuffer, 0, Constants.INT_SIZE);
		return Converter.Bytes2Int(intbuffer, 0);*/
		int rootId = mmpfile.readInt(0, 0);
		//System.out.println("Get BTree root = " + rootId);
		return rootId;
	}
}
